/**
 * @file
 * @author dousha 
 * @date 2020/11/29.
 */

#include <stm32f1xx_hal.h>
#include <string.h>
#include "flash.h"
#include "buttons.h"

void flash_init() {
	if (buttons_get_immediate_state() == BUTTON_ALL) {
		// three buttons are all pressed at the startup
		// TODO: unlock debug mode
		// NOTE: this part of the code should be disabled on release version
		// reset device
		flash_reset_setup();
	} else {
		// TODO: lock debug mode
	}
}

void flash_read_magic(uint32_t *out) {
	memcpy(out, (const uint32_t *) FLASH_MAGIC_ADDR, 16);
}

void flash_write_magic(const uint32_t *in) {
	HAL_FLASH_Unlock();
	for (uint8_t i = 0; i < 4; i++) {
		HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_MAGIC_ADDR + i * 4, in[i]);
	}
	HAL_FLASH_Lock();
}

void flash_read_salt(uint32_t *out) {
	memcpy(out, (const uint32_t *) FLASH_SALT_ADDR, 16);
}

void flash_write_salt(const uint32_t *in) {
	HAL_FLASH_Unlock();
	for (uint8_t i = 0; i < 4; i++) {
		HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_SALT_ADDR + i * 4, in[i]);
	}
	HAL_FLASH_Lock();
}

void flash_reset_setup() {
	uint8_t result;
	HAL_FLASH_Unlock();
	FLASH_EraseInitTypeDef eraser;
	eraser.TypeErase = FLASH_TYPEERASE_PAGES;
	eraser.NbPages = 1;
	eraser.PageAddress = FLASH_MAGIC_ADDR;
	uint32_t errcode = 0;
	result = HAL_FLASHEx_Erase(&eraser, &errcode);
	if (result != HAL_OK) {
		result = HAL_FLASH_GetError();
		if (result > 0) {
			for (;;) ;
		}
	}
	HAL_FLASH_Lock();
}

void flash_finish_setup() {
	HAL_FLASH_Unlock();
	if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_SETUP_INFO, SETUP_MAGIC) != HAL_OK) {
		for (;;) ;
	};
	HAL_FLASH_Lock();
}

uint8_t flash_has_setup() {
	uint32_t value = *((uint32_t *) FLASH_SETUP_INFO);
	return value == SETUP_MAGIC;
}
